import 'dart:io';

import 'package:yaml/yaml.dart' as yaml;

void main() async {
  List<String> unReferenceDependencies = FileUtil.readUnReferenceDependencies();
  print("项目未引用依赖个数：${unReferenceDependencies.length}");

  int markUnReferenceCount = FileUtil.markUnReferenceDependencies(unReferenceDependencies);
  print("项目未引用依赖标注个数：$markUnReferenceCount");
}

class FileUtil {
  /// 标注项目未引用的依赖
  static int markUnReferenceDependencies(List<String> unReferenceDependencies) {
    final file = File('pubspec.yaml');
    final content = file.readAsStringSync();
    final yamlMap = yaml.loadYaml(content);
    final dependencies = Map<String, dynamic>.from(yamlMap['dependencies'] ?? {});

    int unReferencedCount = 0;

    for (var key in unReferenceDependencies) {
      if (dependencies.containsKey(key) && dependencies[key] is! Map) {
        dependencies[key] = "${dependencies[key]} #未使用";
        unReferencedCount++;
      }
    }

    final updatedDependencies = dependenciesToYamlString(dependencies);
    final updatedContent = replaceDependenciesSection(content, updatedDependencies);
    file.writeAsStringSync(updatedContent);

    return unReferencedCount;
  }

  /// 将 dependencies Map 转换为 YAML 格式的字符串
  static String dependenciesToYamlString(Map<String, dynamic> dependencies) {
    final buffer = StringBuffer();
    buffer.writeln('dependencies:');
    dependencies.forEach((key, value) {
      buffer.writeln('  $key: $value');
    });
    return buffer.toString();
  }

  /// 替换 pubspec.yaml 中的 dependencies 部分
  static String replaceDependenciesSection(String originalContent, String newDependenciesContent) {
    final lines = originalContent.split('\n');
    final buffer = StringBuffer();
    bool inDependenciesSection = false;

    for (var line in lines) {
      if (line.trim().startsWith('dependencies:')) {
        inDependenciesSection = true;
        buffer.writeln(newDependenciesContent);
        continue;
      }
      if (inDependenciesSection) {
        if (line.isNotEmpty && !line.startsWith(' ')) {
          inDependenciesSection = false;
        } else {
          continue;
        }
      }
      buffer.writeln(line);
    }
    return buffer.toString();
  }

  /// 读取项目未引用的依赖
  static List<String> readUnReferenceDependencies() {
    Set<String> ymlDependencies = FileUtil.readDependencies();
    List<String> recursionFilePaths = FileUtil.recursionFile("lib");
    Set<String> projectDependencies = {};
    for (var dartFilePath in recursionFilePaths) {
      List<String> fileDependencies = FileUtil.readProjectDartFileDependencies(dartFilePath);
      projectDependencies.addAll(fileDependencies);
    }
    Set<String> differenceDependencies = ymlDependencies.difference(projectDependencies);
    return differenceDependencies.toList();
  }

  /// 递归读取文件
  static List<String> recursionFile(String directoryName) {
    List<String> recursionFilePaths = [];
    Directory directory = Directory(directoryName);
    if (!directory.existsSync()) {
      return [];
    }

    List<FileSystemEntity> list = directory.listSync(recursive: true);
    for (var element in list) {
      FileSystemEntityType fileSystemEntityType = FileSystemEntity.typeSync(element.path);
      if (fileSystemEntityType == FileSystemEntityType.file && element.path.endsWith(".dart")) {
        recursionFilePaths.add(element.path);
      }
    }
    return recursionFilePaths;
  }

  /// 读取dart文件引用的依赖
  static List<String> readProjectDartFileDependencies(String path) {
    if (!path.endsWith(".dart")) {
      return [];
    }

    final dartFile = File(path);
    if (!dartFile.existsSync()) {
      return [];
    }

    List<String> lines = dartFile.readAsLinesSync();
    String prefix0 = "import";
    String prefix1 = "$prefix0 'package:${readProjectName()}";
    String prefix2 = "$prefix0 'package:flutter/";
    String prefix3 = "$prefix0 'package:flutter_localizations/f";
    String prefix4 = "$prefix0 'dart:";

    List<String> dependenciesRelation = [];
    for (var line in lines) {
      if (line.startsWith(prefix0) && (!line.startsWith(prefix1) && !line.startsWith(prefix2) && !line.startsWith(prefix3) && !line.startsWith(prefix4))) {
        dependenciesRelation.add(line);
      }
    }

    List<String> dependenciesNames = [];
    for (var dr in dependenciesRelation) {
      String drFullName = dr.split("$prefix0 'package:").last;
      String drName = drFullName.split("/").first;
      dependenciesNames.add(drName);
    }
    return dependenciesNames;
  }

  /// 读取开发依赖
  static Set<String> readDependencies() {
    final pubspecFile = File('pubspec.yaml');
    if (!pubspecFile.existsSync()) {
      return {};
    }
    final content = pubspecFile.readAsStringSync();
    final yamlMap = yaml.loadYaml(content);
    final dependencies = yamlMap['dependencies'] ?? {};
    Set<String> dependencyNames = {};
    for (var entry in dependencies.entries) {
      if (entry.value is! Map) {
        dependencyNames.add(entry.key);
      }
    }
    return dependencyNames;
  }

  /// 读取项目名称
  static String readProjectName() {
    final pubspecFile = File('pubspec.yaml');
    if (!pubspecFile.existsSync()) {
      return "";
    }
    final content = pubspecFile.readAsStringSync();
    final yamlMap = yaml.loadYaml(content);
    return yamlMap["name"];
  }
}
